#!/usr/bin/env ruby
#
#  Created by sjavey on 2007-10-01.
#  Copyright (c) 2007. All rights reserved.
require 'uri'
require 'net/https'
require 'rexml/document'
require 'digest/md5'

class Share
  
  attr_reader :user
  attr_reader :auth_token
  attr_accessor :session_id
  attr_accessor :session_secret
  attr_accessor :user_full_name
  attr_accessor :root_node
  attr_accessor :doc_nodes # array of docs
  attr_accessor :link_nodes # arrat of link nodes
  attr_accessor :http_response_code
  attr_accessor :http_response_message

  METHOD_POST = "POST"
  METHOD_GET = "GET"
#  API_KEY = "YOUR-KEY"
#  SHARED_SECRET = "YOUR-SECRET"  
  SHARED_SERVER = "api.share.adobe.com"
  SHARED_SERVER_PORT = 443
#  SHARED_SERVER = "localhost"
#  SHARED_SERVER_PORT = 53425
 
  AUTH_TOKEN_PATH = "/webservices/api/v1/auth/"
  SESSION_PATH = "/webservices/api/v1/sessions/"
  MY_LIB_PATH = "/webservices/api/v1/dc/"


  def Share.get_user_from_session(session) 
    @user = session[:user]
    return @user
  end
  
  def initialize(user)
    @user = user
  end

  def get_authorization_token_xml()
    # BUG: if the XML has new line characters then it will fail to be parsed by the server.
    xml = "<request><username>#{@user.email}</username><password>#{@user.password}</password></request>"
  end

  def get_session_xml()
    xml = "<request><authtoken>#{@auth_token}</authtoken></request>"
  end

  def get_authorization_header()
    now = Time::now
    data="#{METHOD_POST} #{AUTH_TOKEN_PATH} apikey=#{API_KEY} calltime=#{now.to_i}000"
    data_plus_secret = "#{data}#{SHARED_SECRET}"
    sig = Digest::MD5::hexdigest(data_plus_secret)
    header = "?apikey=#{API_KEY}&calltime=#{now.to_i}000&sig=#{sig}"
    return header
  end

  def get_session_header()
    now = Time::now
    data="#{METHOD_POST} #{SESSION_PATH} apikey=#{API_KEY} calltime=#{now.to_i}000"
    data_plus_secret = "#{data}#{SHARED_SECRET}"
    sig = Digest::MD5::hexdigest(data_plus_secret)
    header = "?apikey=#{API_KEY}&calltime=#{now.to_i}000&sig=#{sig}"
    return header
  end

  def get_session_authorization_header(method, path)
    now = Time::now
    data="#{method} #{path} apikey=#{API_KEY} calltime=#{now.to_i}000 sessionid=#{@session_id}"
    data_plus_secret = "#{data}#{@session_secret}"
    sig = Digest::MD5::hexdigest(data_plus_secret)
    header = "?apikey=#{API_KEY}&calltime=#{now.to_i}000&sessionid=#{@session_id}&sig=#{sig}"
    return header
  end

  def get_authorization_token
    query_params = get_authorization_header      
    body = get_authorization_token_xml
    response, xml = get_http.post(AUTH_TOKEN_PATH+query_params, body, {'Accept' => 'application/xml'})
    @http_response_code = response.code
    @http_response_message = response.message
    if (response.code == "200")
      document = REXML::Document.new(xml)
      @auth_token = document.root.elements["authtoken"].text
    else
      # puts "invalid login credentials"
      @auth_token = nil
    end
    return @auth_token
  end    

  def start_session
    query_params = get_session_header      
    body = get_session_xml
    response, xml = get_http.post(SESSION_PATH+query_params, body, {'Accept' => 'application/xml'})
    if (response.code == "200")
      document = REXML::Document.new(xml)
      @session_id = document.root.elements["sessionid"].text
      @session_secret = document.root.elements["secret"].text
      @user_full_name = document.root.elements["name"].text
    else
      #puts "Failed to start session"
      @http_response_code = response.code
      @http_response_message = response.message
    end
  end    

  def get_my_library
    query_params = get_session_authorization_header(METHOD_GET, MY_LIB_PATH)      
    response, xml = get_http.get(MY_LIB_PATH+query_params, {'Accept' => 'application/xml'})
    if (response.code == "200")
      document = REXML::Document.new(xml)
      @root_node = document.root.elements["node"]
      @doc_nodes = Array.new()
      @link_nodes = Array.new()
      kids = document.root.elements["children"]
      kids.each {|t|
        node = Node.new(t)
        if (node.is_link)
          @link_nodes << node
        else
          @doc_nodes << node  
        end          
      }
    else
      #puts "Failed to get the library"
      @http_response_code = response.code
      @http_response_message = response.message
    end
  end

  def get_doc(doc_id, rendition)
    path = "#{MY_LIB_PATH}#{doc_id}/#{rendition}/"
    query_params = get_session_authorization_header(METHOD_GET, path)      
    response, data = get_http.get(path+query_params, {'Accept' => 'application/xml'})
    if (response.code == "200")
      return data
    else
      # puts "Failed to get rendition: #{response.code}, #{response.message}"
      return nil
    end
  end

  
  private

  def get_http
    http = Net::HTTP.new(SHARED_SERVER, SHARED_SERVER_PORT)
    http.use_ssl = true
    return http
  end

end
